﻿using System;
using System.IO;
using System.Linq;
using System.Net;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Activation;
using System.Collections.Generic;
using System.ServiceModel.Web;
using System.Threading;
using System.Web;
using LetsDoIt.Common;
using LetsDoIt.Common.Constants;
using LetsDoIt.Common.ResponseMessages;
using LetsDoIt.Logging;
using LetsDoItWS.BO;
using Microsoft.ServiceModel.Web;

[assembly: ContractNamespace("", ClrNamespace = "")]
namespace LetsDoItWS
{
	// TODO: Modify the service behavior settings (instancing, concurrency etc) based on the service's requirements. Use ConcurrencyMode.Multiple if your service implementation is thread-safe.
	// TODO: NOTE: Please set IncludeExceptionDetailInFaults to false in production environments
	[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
	[ServiceContract(Namespace = "")]
	public class WastesService
	{
		//setup version
		private const string version = Versions.Version_1_0;


		[OperationContract]
		[WebInvoke(Method = "POST",
			RequestFormat = WebMessageFormat.Xml,
			ResponseFormat = WebMessageFormat.Xml,
			BodyStyle = WebMessageBodyStyle.Bare,
			UriTemplate = version + "/waste")]
		[WebHelp(Comment = "Insert a waste point")]
		public ResponseWaste CreateWastePoint(GarbagePile request)
		{
			return CreateWastePointGeneric(request);
		}

		[OperationContract]
		[WebInvoke(Method = "POST",
			RequestFormat = WebMessageFormat.Json,
			ResponseFormat = WebMessageFormat.Json,
			BodyStyle = WebMessageBodyStyle.Bare,
			UriTemplate = version + "/waste/json")]
		[WebHelp(Comment = "Insert a waste point")]
		public ResponseWaste CreateWastePointJson(GarbagePile request)
		{
			return CreateWastePointGeneric(request);
		}

		private ResponseWaste CreateWastePointGeneric(GarbagePile request)
		{
			WebOperationContext ctx = WebOperationContext.Current;
			ResponseWaste response = new ResponseWaste();
			response.LocalID = request.ID;
			try
			{
				using (ldirdbEntities dataContext = new ldirdbEntities())
				{
					TrashPoint point = CreateTrashPoint(request, dataContext);

					dataContext.AddToTrashPoints(point);
					dataContext.SaveChanges(true);
                    //
				    dataContext.UpdateTrashPointCountyByID(point.id_TPT);
                    //
					response.ServerID = point.id_TPT.ToString();
					response.Succes = true;
				}
				if (ctx != null)
				{
					ctx.OutgoingResponse.StatusCode = HttpStatusCode.Created;
				}
				return response;
			}
			catch (Exception ex)
			{
				LoggerManager.Current.ErrorFormat(typeof(object), "WS Error : {0}", ex);
				if (ctx != null)
				{
					ctx.OutgoingResponse.StatusCode = HttpStatusCode.BadRequest;
					ctx.OutgoingResponse.StatusDescription = ex.ToString();

					throw new WebProtocolException(HttpStatusCode.BadRequest, ex.ToString(), null);
				}
			}
			return null;
		}

        private TrashPoint CreateTrashPoint(GarbagePile request, ldirdbEntities dataContext)
		{
			TrashPoint point = new TrashPoint();
			point.latitude_TPT = (decimal)request.Location.Latitude;
			point.longitude_TPT = (decimal)request.Location.Longitude;
			point.diameter_TPT = request.Diameter;
			point.height_TPT = request.Height;
			point.description_TPT = request.Description;
			point.bad_road_rain_TPT = request.IsAccessDifficultOnRain ? "Y" : string.Empty;
			point.bad_road_TPT = request.IsAccessDifficult ? "Y" : string.Empty;
			point.date_time_TPT = request.PostingDateTime;
			//percentages
			point.perc_paper_TPT = request.PercentageCarton;
			point.perc_glass_TPT = request.PercentageGlass;
			point.perc_metal_TPT = request.PercentageMetal;
			point.perc_non_reciclable_TPT = request.PercentageOrganic;
			point.perc_plastic_TPT = request.PercentagePlastic;
			point.perc_construction_TPT = request.PercentageRawMatterials;
			point.perc_rubber_TPT = request.PercentageRubber;
			point.perc_big_volume_TPT = request.PercentageVolume;
            //
		    point.test_tpt = request.IsTest ? "Y" : string.Empty;
		    point.code_tpt = request.ID;
		    point.dispersed_TPT = request.IsDispersed ? "Y" : string.Empty;
		    point.bag_eq_TPT = request.BagEq;
            point.width_TPT = request.Width;
            point.length_TPT = request.Length;

			//fill user
			point.exclude_TPT = string.Empty;
			point.user_TPT = null;
			string userName = Thread.CurrentPrincipal.Identity.Name;
			User userData = dataContext.Users.FirstOrDefault(u => u.username == userName);
			if (userData!=null)
				point.user_TPT = userData.id;
			return point;
		}


		[OperationContract]
		[WebInvoke(Method = "POST",
			RequestFormat = WebMessageFormat.Xml,
			ResponseFormat = WebMessageFormat.Xml,
			BodyStyle = WebMessageBodyStyle.Bare,
			UriTemplate = version + "/wastes")]
		[WebHelp(Comment = "Insert a list of waste point")]
		/// sample
		/// <garbage><County>IS</County><Description>String content</Description><Diameter>10</Diameter><Height>2</Height><ID>1627aea5-8e0a-4371-9022-9b504344e724</ID><IsAccessDifficult>true</IsAccessDifficult><IsAccessDifficultOnRain>true</IsAccessDifficultOnRain><Location><Latitude>45.17</Latitude><Longitude>27.13</Longitude></Location><PercentageCarton>27</PercentageCarton><PercentageGlass>27</PercentageGlass><PercentageMetal>47</PercentageMetal><PercentageOrganic>2</PercentageOrganic><PercentagePlastic>36</PercentagePlastic><PercentageRawMatterials>21</PercentageRawMatterials><PercentageRubber>14</PercentageRubber><PercentageVolume>87</PercentageVolume></garbage>
		public ResponseWastes CreateWastePoints(GarbagePiles request)
		{
			return CreateWastePointsGeneric(request);
		}
		

		[OperationContract]
		[WebInvoke(Method = "POST",
			RequestFormat = WebMessageFormat.Json,
			ResponseFormat = WebMessageFormat.Json,
			BodyStyle = WebMessageBodyStyle.Bare,
			UriTemplate = version + "/wastes/json")]
		[WebHelp(Comment = "Insert a list of waste point")]
		public ResponseWastes CreateWastePointsJson(GarbagePiles request)
		{
			return CreateWastePointsGeneric(request);
		}

		private ResponseWastes CreateWastePointsGeneric(GarbagePiles request)
		{
			WebOperationContext ctx = WebOperationContext.Current;
			ResponseWastes response = new ResponseWastes();
			try
			{
				using (ldirdbEntities dataContext = new ldirdbEntities())
				{
					List<TrashPoint> listTP = new List<TrashPoint>();
					foreach (GarbagePile pile in request)
					{
						ResponseWaste responsePile = new ResponseWaste();
						responsePile.LocalID = pile.ID;

						TrashPoint point = CreateTrashPoint(pile, dataContext);

						dataContext.AddToTrashPoints(point);
						listTP.Add(point);

						responsePile.ServerID = point.id_TPT.ToString();
						responsePile.Succes = true;
						response.Add(responsePile);
					}

					dataContext.SaveChanges(true);

					for (int x = 0; x < listTP.Count; x++)
					{
						response[x].ServerID = listTP[x].id_TPT.ToString();
					}
				}
				if (ctx != null)
				{
					ctx.OutgoingResponse.StatusCode = HttpStatusCode.Created;
				}
				return response;
			}
			catch (Exception ex)
			{
				LoggerManager.Current.ErrorFormat(typeof(object), "WS Error : {0}", ex);
				if (ctx != null)
				{
					ctx.OutgoingResponse.StatusCode = HttpStatusCode.BadRequest;
					ctx.OutgoingResponse.StatusDescription = ex.ToString();

					throw new WebProtocolException(HttpStatusCode.BadRequest, ex.ToString(), null);
				}
			}
			return null;
		}



		[OperationContract]
		[WebInvoke(Method = "POST",
			UriTemplate = version + "/images/{wasteId}")]
		[WebHelp(Comment = "Uploads an image for a waste point")]
		public ResponseImage UploadWastePointImage(string wasteId, Stream image )
		{
			WebOperationContext ctx = WebOperationContext.Current;
			ResponseImage response = new ResponseImage();
			try
			{
				string uderId = "0";//0 means anonymous user
				TrashPoint tp;
				using (ldirdbEntities dataContext = new ldirdbEntities())
				{
					string userName = Thread.CurrentPrincipal.Identity.Name;
					User userData = dataContext.Users.FirstOrDefault(u => u.username == userName);
					if (userData != null)
						uderId = userData.id.ToString();
					int intWasteId = Convert.ToInt32(wasteId);
					tp = dataContext.TrashPoints.FirstOrDefault(t => t.id_TPT == intWasteId);
				}
				if (tp != null)
				{
					byte[] imageContent;
					byte[] buffer = new byte[4096];
					using (MemoryStream ms = new MemoryStream()) 
					{ 
						int read; 
						while ((read = image.Read(buffer, 0, buffer.Length)) > 0) 
						{ 
							ms.Write(buffer, 0, read); 
						} 
						imageContent = ms.ToArray(); 
					}

					if (ImageStorageFactory.SaveImage(wasteId, uderId, imageContent, tp))
					{
						response.Succes = true;
					}
				}
				else
				{
					throw new WebProtocolException(HttpStatusCode.BadRequest, "Invalid waste id", null);
				}
			}
			catch (Exception ex)
			{
				LoggerManager.Current.ErrorFormat(typeof(object), "WS Error : {0}", ex);
				if (ctx != null)
				{
					ctx.OutgoingResponse.StatusCode = HttpStatusCode.BadRequest;
					ctx.OutgoingResponse.StatusDescription = ex.ToString();

					throw new WebProtocolException(HttpStatusCode.BadRequest, ex.ToString(), null);
				}
			}
			return response;
		}



        [OperationContract]
        [WebInvoke(Method = "GET",
            ResponseFormat = WebMessageFormat.Xml,
            BodyStyle = WebMessageBodyStyle.Bare,
            UriTemplate = version + "/images/{wasteId}/first")]
        [WebHelp(Comment = "Gets first image URL for a waste point")]
        public string GetFirstWastePointImageURL(string wasteId)
        {
            WebOperationContext ctx = WebOperationContext.Current;
            string result = string.Empty;
            try
            {
                int intWasteId = Convert.ToInt32(wasteId);
                result = ImageStorageFactory.GetFirstImageURL(intWasteId);
            }
            catch (Exception ex)
            {
                LoggerManager.Current.ErrorFormat(typeof(object), "WS Error : {0}", ex);
                if (ctx != null)
                {
                    ctx.OutgoingResponse.StatusCode = HttpStatusCode.BadRequest;
                    ctx.OutgoingResponse.StatusDescription = ex.ToString();

                    throw new WebProtocolException(HttpStatusCode.BadRequest, ex.ToString(), null);
                }
            }
            return result;
        }

        [OperationContract]
        [WebInvoke(Method = "GET",
            ResponseFormat = WebMessageFormat.Json,
            UriTemplate = version + "/images/{wasteId}/first/json")]
        [WebHelp(Comment = "Gets first image URL for a waste point - json")]
        public string GetFirstWastePointImageURLJson(string wasteId)
        {
            WebOperationContext ctx = WebOperationContext.Current;
            string result = string.Empty;
            try
            {
                int intWasteId = Convert.ToInt32(wasteId);
                result = ImageStorageFactory.GetFirstImageURL(intWasteId);
            }
            catch (Exception ex)
            {
                LoggerManager.Current.ErrorFormat(typeof(object), "WS Error : {0}", ex);
                if (ctx != null)
                {
                    ctx.OutgoingResponse.StatusCode = HttpStatusCode.BadRequest;
                    ctx.OutgoingResponse.StatusDescription = ex.ToString();

                    throw new WebProtocolException(HttpStatusCode.BadRequest, ex.ToString(), null);
                }
            }
            return result;
        }

        [OperationContract]
        [WebInvoke(Method = "GET",
            ResponseFormat = WebMessageFormat.Xml,
            BodyStyle = WebMessageBodyStyle.Bare,
            UriTemplate = version + "/images/{wasteId}/second")]
        [WebHelp(Comment = "Gets second image URL for a waste point")]
        public string GetSecondWastePointImageURL(string wasteId)
        {
            WebOperationContext ctx = WebOperationContext.Current;
            string result = string.Empty;
            try
            {
                int intWasteId = Convert.ToInt32(wasteId);
                result = ImageStorageFactory.GetSecondImageURL(intWasteId);
            }
            catch (Exception ex)
            {
                LoggerManager.Current.ErrorFormat(typeof(object), "WS Error : {0}", ex);
                if (ctx != null)
                {
                    ctx.OutgoingResponse.StatusCode = HttpStatusCode.BadRequest;
                    ctx.OutgoingResponse.StatusDescription = ex.ToString();

                    throw new WebProtocolException(HttpStatusCode.BadRequest, ex.ToString(), null);
                }
            }
            return result;
        }

        [OperationContract]
        [WebInvoke(Method = "GET",
            ResponseFormat = WebMessageFormat.Json,
            UriTemplate = version + "/images/{wasteId}/second/json")]
        [WebHelp(Comment = "Gets second image URL for a waste point - json")]
        public string GetSecondWastePointImageURLJson(string wasteId)
        {
            WebOperationContext ctx = WebOperationContext.Current;
            string result = string.Empty;
            try
            {
                int intWasteId = Convert.ToInt32(wasteId);
                result = ImageStorageFactory.GetSecondImageURL(intWasteId);
            }
            catch (Exception ex)
            {
                LoggerManager.Current.ErrorFormat(typeof(object), "WS Error : {0}", ex);
                if (ctx != null)
                {
                    ctx.OutgoingResponse.StatusCode = HttpStatusCode.BadRequest;
                    ctx.OutgoingResponse.StatusDescription = ex.ToString();

                    throw new WebProtocolException(HttpStatusCode.BadRequest, ex.ToString(), null);
                }
            }
            return result;
        }
	}
}
